package com.oig.sys.query;

import cn.hutool.core.collection.CollectionUtil;
import com.oig.sys.query.support.*;
import com.oig.sys.query.support.module.ConditionExp;
import com.oig.sys.query.support.module.QueryExpression;
import com.oig.sys.query.support.module.SqlAndParams;

import java.util.Map;


public class QuerySqlBuilder {

    private QueryExpParser queryExpParser = new JsonExpQueryParser();
    private QuerySqlConvert querySqlConvert = new DefaultQuerySqlConvert();
    private QueryConditionExpParser queryConditionExpParser = new MongoExpConditionParser();
    private QueryConditionCovert queryConditionCovert = new DefaultConditionCovert();


    public QuerySqlBuilder queryExpParser(QueryExpParser queryExpParser){
        this.queryExpParser = queryExpParser;
        return this;
    }

    public QuerySqlBuilder querySqlConvert(QuerySqlConvert querySqlConvert){
        this.querySqlConvert = querySqlConvert;
        return this;
    }

    public QuerySqlBuilder queryConditionExpParser(QueryConditionExpParser queryConditionExpParser){
        this.queryConditionExpParser = queryConditionExpParser;
        return this;
    }

    public QuerySqlBuilder queryConditionCovert(QueryConditionCovert queryConditionCovert){
        this.queryConditionCovert = queryConditionCovert;
        return this;
    }

    /**
     * 只有查询语句
     */
    public SqlAndParams covertOnlyQuerySql(String jsonText, SysCommQueryReq queryReq){
        QueryExpression queryExpression = queryExpParser.expressParser(jsonText) ;
        String querySql = querySqlConvert.selectSqlCovert(queryExpression) ;
        StringBuilder querySb = new StringBuilder();
        querySb.append(querySql) ;

        SqlAndParams conditionSqlAndParams = this.covertWhereSql(queryReq, queryExpression);
        String whereSql = conditionSqlAndParams.getSql();
        if (whereSql != null && !whereSql.equals(QueryConditionCovert.where)) {
            querySb.append(whereSql) ;
        }
        if (queryExpression.getGroupBy()!=null){
            querySb.append(querySqlConvert.groupSqlCovert(queryExpression.getGroupBy())) ;
        }
        if (queryReq.getSort()==null||queryReq.getSort().isEmpty()){
            querySb.append(querySqlConvert.defaultOrderSqlCovert(queryExpression.getOrderBy())) ;
        } else {
            querySb.append(querySqlConvert.orderSqlCovert(queryExpression, queryReq.getSort())) ;
        }
        conditionSqlAndParams.setSql(querySb.toString());
        return conditionSqlAndParams;
    }


    private SqlAndParams covertWhereSql(SysCommQueryReq queryReq, QueryExpression queryExpression){
        SqlAndParams conditionSqlAndParams = null;
        if (queryReq.getWhere()!=null){
            ConditionExp conditionExp=queryConditionExpParser.conditionParer(queryReq.getWhere()) ;
            if (conditionExp!=null && (CollectionUtil.isNotEmpty(conditionExp.getExpList()) || CollectionUtil.isNotEmpty(conditionExp.getInnerCondition()))){
                conditionSqlAndParams = queryConditionCovert.whereSqlCovert(conditionExp, queryExpression) ;
            }
        }
        if (queryReq.getInnerWhere()!=null){
            ConditionExp conditionExp = null ;
            if (queryReq.getInnerWhere() instanceof ConditionExp){
                conditionExp=(ConditionExp) queryReq.getInnerWhere() ;
            } else if (queryReq.getInnerWhere() instanceof Map){
                conditionExp=queryConditionExpParser.conditionParer(queryReq.getInnerWhere()) ;
            }
            if (conditionExp!=null) {
                conditionSqlAndParams = queryConditionCovert.addConditionCovert(conditionSqlAndParams, conditionExp, queryExpression);
            }
        }
        if (conditionSqlAndParams==null){
            conditionSqlAndParams = new SqlAndParams();
        }
        return conditionSqlAndParams;
    }

    /**
     * 包含count语句，分页查询用
     */
    public SqlAndParams covertSql(String jsonText, SysCommQueryReq queryReq){
        QueryExpression queryExpression = queryExpParser.expressParser(jsonText) ;
        String querySql = querySqlConvert.selectSqlCovert(queryExpression) ;
        String countSql = querySqlConvert.countSqlCovert(queryExpression) ;
        SqlAndParams conditionSqlAndParams = this.covertWhereSql(queryReq, queryExpression);

        StringBuilder querySb = new StringBuilder();
        StringBuilder countSb = new StringBuilder();
        querySb.append(querySql) ;
        countSb.append(countSql) ;
        String whereSql = conditionSqlAndParams.getSql();
        if (whereSql != null && !whereSql.equals(QueryConditionCovert.where)) {
            querySb.append(whereSql) ;
            countSb.append(whereSql) ;
        }
        if (queryExpression.getGroupBy()!=null){
            String groupSql = querySqlConvert.groupSqlCovert(queryExpression.getGroupBy());
            querySb.append(groupSql) ;
        }
        if (queryReq.getSort()!=null && !queryReq.getSort().isEmpty()){
            querySb.append(querySqlConvert.orderSqlCovert(queryExpression, queryReq.getSort())) ;
        } else {
            querySb.append(querySqlConvert.defaultOrderSqlCovert(queryExpression.getOrderBy())) ;
        }
        if (queryReq.getPage()!=null){
            querySb.append(querySqlConvert.limitSqlCovert(queryReq.getPage())) ;
        }
        conditionSqlAndParams.setSql(querySb.toString());
        conditionSqlAndParams.setCountSql(countSb.toString());
        return conditionSqlAndParams;
    }


}
